﻿using System;
using System.Collections.Generic;
using System.Linq;
using HK.Core.Extend;
using HK.Core.GUIEx.Protocol.Attribute;
using HK.Editor.Common;
using HK.Editor.Defines.Data;
using HK.Editor.Defines.Protocol.Data;
using HK.Editor.Defines.Protocol.Window;
using HK.Editor.GUIEx.Data;
using HK.Editor.GUIEx.Styles;
using HK.Editor.GUIEx.TreeView.Control;
using HK.Editor.GUIEx.Window;
using HK.Editor.Utils;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;

namespace HK.Editor.Defines.Window
{
    /// <summary>
    /// 宏定义窗体
    /// </summary>
    public class DefinesWindow : MultiColsWindow<DefinesWindow, WindowConf, DefinesData, DefineInfo>, IDefinesWindow<DefinesWindow, DefinesData, DefineInfo>
    {
        
#region Menu

        /// <summary>
        /// 显示宏定义窗口.
        /// </summary>
        [MenuItem(EditorConst.MENU_TXT_TOOL_DEFINES, false, EditorConst.MENU_PRIORITY_TOOL_DEFINES)]
        static void ShowWindow()
        {
            var conf = WindowConf.Create("宏定义一栏", new Rect(0, 0, 600, 400), (int)GUIOperateOptions.DefinesWindow);
            // 显示窗体
            ShowWindow(conf, true, true);
        }

#endregion

		/// <summary>
		/// 编辑状态
		/// </summary>
		public DefineEditState State { get; private set; } = DefineEditState.Idle;
		
		/// <summary>
		/// 初始化数据.
		/// </summary>
		protected override bool InitData()
		{
			if (!base.InitData())
			{
				return false;
			}
			
			// 根据现有工程设定宏，刷新
			if (RefreshDefines())
			{
				Export();
			}
			return true;
		}
		
		/// <summary>
		/// 刷新宏
		/// </summary>
		/// <returns>true:存在刷新宏; false:不存在;</returns>
		private bool RefreshDefines()
		{
			var dirty = false;
			// 取得当前工程的宏列表
			// Android
			var androidDefines = DefinesSetting.GetDefinesByBuildTargetGroup(BuildTargetGroup.Android);
			if (!string.IsNullOrEmpty(androidDefines))
			{
				if (Data.ResetDefines(androidDefines, BuildTargetGroup.Android))
				{
					dirty = true;
				}
			}
			
			// iOS
			var iosDefines = DefinesSetting.GetDefinesByBuildTargetGroup(BuildTargetGroup.iOS);
			if (!string.IsNullOrEmpty(iosDefines))
			{
				if (Data.ResetDefines(iosDefines, BuildTargetGroup.iOS))
				{
					if (!dirty)
					{
						dirty = true;
					}
				}
			}
			
			// Pc
			var pcDefines = DefinesSetting.GetDefinesByBuildTargetGroup(BuildTargetGroup.Standalone);
			if (!string.IsNullOrEmpty(pcDefines))
			{
				if (Data.ResetDefines(pcDefines, BuildTargetGroup.Standalone))
				{
					if (!dirty)
					{
						dirty = true;
					}
				}
			}
			
			// Ps4
			var ps4Defines = DefinesSetting.GetDefinesByBuildTargetGroup(BuildTargetGroup.PS4);
			if (!string.IsNullOrEmpty(ps4Defines))
			{
				if (Data.ResetDefines(ps4Defines, BuildTargetGroup.PS4))
				{
					if (!dirty)
					{
						dirty = true;
					}
				}
			}
			
			// Ps5
			var ps5Defines = DefinesSetting.GetDefinesByBuildTargetGroup(BuildTargetGroup.PS5);
			if (!string.IsNullOrEmpty(ps5Defines))
			{
				if (Data.ResetDefines(ps5Defines, BuildTargetGroup.PS5))
				{
					if (!dirty)
					{
						dirty = true;
					}
				}
			}
			
			// XboxOne
			var xboxOneDefines = DefinesSetting.GetDefinesByBuildTargetGroup(BuildTargetGroup.XboxOne);
			if (!string.IsNullOrEmpty(xboxOneDefines))
			{
				if (Data.ResetDefines(xboxOneDefines, BuildTargetGroup.XboxOne))
				{
					if (!dirty)
					{
						dirty = true;
					}
				}
			}

			return dirty;
		}

#region Contents
        
		protected GUIContent _defineLabel = null;
		protected GUIContent _tipsLabel = null;

		/// <summary>
		/// 初始化GUI Content
		/// </summary>
		protected override void InitGuiContents()
		{
			base.InitGuiContents();
			
			_defineLabel = UtilsGUIEx.CreateGuiContent("名称");
			_tipsLabel = UtilsGUIEx.CreateGuiContent("Tips");
		}
		
		private Dictionary<int, GUIContent> _defineCaptions = new Dictionary<int, GUIContent>();

		/// <summary>
		/// 取得宏标题
		/// </summary>
		/// <param name="iId">宏Id</param>
		/// <param name="iDefine">宏</param>
		/// <param name="iTips">Tips</param>
		/// <returns>宏标题</returns>
		private GUIContent GetDefineCaption(int iId, string iDefine, string iTips)
		{
			if (_defineCaptions.TryGetValue(iId, out var oCaption))
			{
				if (null == oCaption)
				{
					oCaption = UtilsGUIEx.CreateGuiContent(iDefine, iTips);
					_defineCaptions[iId] = oCaption;
				}
				else
				{
					oCaption.text = iDefine;
					oCaption.tooltip = iTips;
				}
			}
			else
			{
				oCaption = UtilsGUIEx.CreateGuiContent(iDefine, iTips);
				_defineCaptions.Add(iId, oCaption);
			}

			return oCaption;
		}

#endregion

#region Size&Rect

		private static readonly float IdWidth = 30.0f;
		private static readonly float NameWidth = 200.0f;
		
		private static readonly float EditDefineLabelWidth = 60.0f;
		private static readonly float EditButtonsWidth = 140.0f;
		private static readonly float EditToggleAndroidWidth = 90.0f;
		private static readonly float EditToggleIosWidth = 60.0f;
		private static readonly float EditTogglePcWidth = 60.0f;
		private static readonly float EditTogglePs4Width = 65.0f;
		private static readonly float EditTogglePs5Width = 65.0f;
		private static readonly float EditToggleXboxoneWidth = 90.0f;
		
		private static readonly float DefineEditLineHeight = SingleLineHeight + VerticalSpacing * 2;
		private static readonly float TipsEditLineHeight = SingleLineHeight + VerticalSpacing * 2;
		private static readonly float PlatformsEditLineHeight = SingleLineHeight + VerticalSpacing * 4;
		
		private static readonly float EditPanelHeight = DefineEditLineHeight + VerticalSpacing +
		                                                TipsEditLineHeight + VerticalSpacing +
		                                                PlatformsEditLineHeight + VerticalSpacing;
		
		/// <summary>
		/// 树形视图显示区域
		/// </summary>
		public override Rect TreeRect => new Rect(base.TreeRect.x, base.TreeRect.y, Width - 40, Height - 120);

#endregion

#region TableTree
        
		/// <summary>
		/// 生成表头
		/// </summary>
		/// <param name="iWidth">TableView宽度</param>
		/// <returns>表头</returns>
		protected override MultiColumnHeaderState GenerateTableHeader(float iWidth)
		{
			var nameWidth = iWidth * 0.3f;
			nameWidth = NameWidth >= nameWidth ? NameWidth : nameWidth;
			var platformWidth = (iWidth - IdWidth - nameWidth) / 6.0f;
			
			var columns = new[] 
			{
				new MultiColumnHeaderState.Column 
				{
					headerContent = new GUIContent("No"),
					contextMenuText = "No",
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = IdWidth, 
					minWidth = IdWidth * 0.6f,
					maxWidth = IdWidth * 2.0f,
					autoResize = false,
					allowToggleVisibility = true
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = new GUIContent("宏名"),
					headerTextAlignment = TextAlignment.Left,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = nameWidth, 
					minWidth = nameWidth * 0.6f,
					maxWidth = nameWidth * 1.5f,
					autoResize = false,
					allowToggleVisibility = false
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = GuiExHelper.AndroidContent,
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = platformWidth,
					minWidth = platformWidth * 0.6f,
					maxWidth = platformWidth * 1.5f,
					autoResize = true
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = GuiExHelper.IosContent,
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = platformWidth,
					minWidth = platformWidth * 0.6f,
					maxWidth = platformWidth * 1.5f,
					autoResize = true,
					allowToggleVisibility = true
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = GuiExHelper.PcOneContent,
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = platformWidth,
					minWidth = platformWidth * 0.6f,
					maxWidth = platformWidth * 1.5f,
					autoResize = true
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = GuiExHelper.Ps4Content,
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = platformWidth,
					minWidth = platformWidth * 0.6f,
					maxWidth = platformWidth * 1.5f,
					autoResize = true
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = GuiExHelper.Ps5Content,
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = platformWidth,
					minWidth = platformWidth * 0.6f,
					maxWidth = platformWidth * 1.5f,
					autoResize = true
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = GuiExHelper.XboxOneContent,
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = platformWidth,
					minWidth = platformWidth * 0.6f,
					maxWidth = platformWidth * 1.5f,
					autoResize = true
				},
				new MultiColumnHeaderState.Column 
				{
					headerContent = new GUIContent("操作"),
					headerTextAlignment = TextAlignment.Center,
					sortedAscending = true,
					sortingArrowAlignment = TextAlignment.Right,
					width = platformWidth,
					minWidth = platformWidth * 0.6f,
					maxWidth = platformWidth * 1.5f,
					autoResize = true
				}
			};
            
			var state =  new MultiColumnHeaderState(columns);
			return state;
		}
        
		/// <summary>
		/// 树枝列表
		/// </summary>
		protected override IList<DefineInfo> Branches => Data.Defines;

		/// <summary>
		/// 列数
		/// </summary>
		protected override int ColumnsCount => Enum.GetValues(typeof(DefinesColumns)).Length;
        
#region Sort
        
		/// <summary>
		/// 排序选项
		/// </summary>
		private DefinesSortOption[] _sortOptions = new []
		{
			DefinesSortOption.Id,
			DefinesSortOption.Name,
			DefinesSortOption.Android,
			DefinesSortOption.iOS,
			DefinesSortOption.Pc,
			DefinesSortOption.Ps4,
			DefinesSortOption.Ps5,
			DefinesSortOption.XboxOne
		};

		/// <summary>
		/// 根据列排序
		/// </summary>
		/// <param name="iHeaderColumns">头部列</param>
		/// <param name="iRoot">根节点</param>
		protected override void SortByColumns(MultiColumnHeader iHeaderColumns, TreeViewItem iRoot)
		{
			if(null == iHeaderColumns || null == iRoot) return;
            var sortedColumns = iHeaderColumns.state.sortedColumns;
            if (0 >= sortedColumns.Length) return;

            var rows = iRoot.children.Cast<TreeViewRow<DefineInfo>>();
            var orderedQuery = InitialOrder (iHeaderColumns, rows, sortedColumns);
            for (var idx = 1; idx < sortedColumns.Length; ++idx)
            {
                var sortOption = _sortOptions[sortedColumns[idx]];
                var ascending = iHeaderColumns.IsSortedAscending(sortedColumns[idx]);
                switch (sortOption)
                {
                    case DefinesSortOption.Id:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.Name, ascending);
                        break;
                    case DefinesSortOption.Name:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.Name, ascending);
                        break;
                    case DefinesSortOption.Android:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.Android, ascending);
                        break;
                    case DefinesSortOption.iOS:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.iOS, ascending);
                        break;
                    case DefinesSortOption.Pc:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.Pc, ascending);
                        break;
                    case DefinesSortOption.Ps4:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.Ps4, ascending);
                        break;
                    case DefinesSortOption.Ps5:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.Ps5, ascending);
                        break;
                    case DefinesSortOption.XboxOne:
                        orderedQuery = orderedQuery.ThenBy(iL => iL.Data.XboxOne, ascending);
                        break;
                    default:
	                    throw new TableTreeUnknownSortOptionsException($"Unknown Sort Option:{sortOption}");
	                    break;
                }
            }

            iRoot.children = orderedQuery.Cast<TreeViewItem> ().ToList ();
		}
        
		/// <summary>
		/// 初始化排序
		/// </summary>
		/// <param name="iHeaderColumns">头部列</param>
		/// <param name="iRows">行列表</param>
		/// <param name="iColumnIndexes">列索引列表</param>
		/// <returns>可排序的列表</returns>
		protected override IOrderedEnumerable<TreeViewRow<DefineInfo>> InitialOrder(
			MultiColumnHeader iHeaderColumns, IEnumerable<TreeViewRow<DefineInfo>> iRows, 
			int[] iColumnIndexes)
		{
			var sortColIndex = _sortOptions[iColumnIndexes[0]];
			var ascending = iHeaderColumns.IsSortedAscending(iColumnIndexes[0]);
			switch (sortColIndex)
			{
				case DefinesSortOption.Id:
					return iRows.Order(iL => iL.Data.Name, ascending);
				case DefinesSortOption.Name:
					return iRows.Order(iL => iL.Data.Name, ascending);
				case DefinesSortOption.Android:
					return iRows.Order(iL => iL.Data.Android, ascending);
				case DefinesSortOption.iOS:
					return iRows.Order(iL => iL.Data.iOS, ascending);
				case DefinesSortOption.Pc:
					return iRows.Order(iL => iL.Data.Pc, ascending);
				case DefinesSortOption.Ps4:
					return iRows.Order(iL => iL.Data.Ps4, ascending);
				case DefinesSortOption.Ps5:
					return iRows.Order(iL => iL.Data.Ps5, ascending);
				case DefinesSortOption.XboxOne:
					return iRows.Order(iL => iL.Data.XboxOne, ascending);
				default:
					throw new TableTreeUnknownColumnException($"Unknown Sort Col Index:{sortColIndex}");
					break;
			}
		}
        
#endregion

#endregion

#region Options

		/// <summary>
		/// 帮助文档Url
		/// </summary>
		protected override string HelpfulUrl => "http://192.168.12.250/Resonance/Edenreborn";

#endregion
        
#region Data

		/// <summary>
		/// 当前编辑宏
		/// </summary>
		private IDefineInfo _curDefine = DefineInfo.Create();

#endregion

#region Events

		/// <summary>
		/// 追加按钮点击事件
		/// </summary>
		/// <param name="iDefine">宏信息</param>
		private void OnAddBtnClicked(IDefineInfo iDefine)
		{
            if(!Data.AddDefine(iDefine)) return;

            // 刷新
            NeedRefresh = true;
			// 重置控件焦点
			UtilsGUIEx.ResetControlFocus();
			
			// 导出
			Export();
		}

		/// <summary>
		/// 保存按钮点击事件
		/// </summary>
		/// <param name="iDefine">宏信息</param>
		private void OnSaveBtnClicked(IDefineInfo iDefine)
		{
			if (null == iDefine || !iDefine.Valid)
			{
				State = DefineEditState.Idle;
				return;
			}

			if (!Data.SaveDefine(iDefine))
			{
				State = DefineEditState.Idle;
				return;
			}
			
			// 刷新
			NeedRefresh = true;
			// 重置控件焦点
			UtilsGUIEx.ResetControlFocus();
			
			// 导出
			Export();
			_defineCaptions.Clear();
			
			State = DefineEditState.Idle;
		}
		
		/// <summary>
		/// 删除按钮点击事件
		/// </summary>
		/// <param name="iDefine">宏信息</param>
		private void OnDelBtnClicked(IDefineInfo iDefine)
		{
			if (null == iDefine || !iDefine.Valid)
			{
				State = DefineEditState.Idle;
				return;
			}

			if (!Data.DelDefine(iDefine))
			{
				State = DefineEditState.Idle;
				return;
			}
			
			// 刷新
			NeedRefresh = true;
			// 重置控件焦点
			UtilsGUIEx.ResetControlFocus();
			
			// 导出
			Export();
			
			State = DefineEditState.Idle;
		}

#endregion
        
		/// <summary>
		/// 应用
		/// </summary>
        public override void Apply()
        {
            Data.Apply();
            
            // 关闭窗体
            Close();
        }
		
#region Draw

		/// <summary>
		/// 绘制窗体Body
		/// </summary>
		/// <param name="iRect">制矩形范围</param>
		/// <param name="iEvent">Event</param>
		/// <returns>制矩形范围</returns>
		protected override Rect DrawWinBody(Rect iRect, Event iEvent)
		{
		    var displayRect = iRect;

		    var searchBarRect = displayRect;
		    searchBarRect.height = SingleLineHeight;
		    if (Searchable)
		    {
			    TableTree.SearchKey = SearchBar.OnGUI (searchBarRect, TableTree.SearchKey);
		    }

		    var treeRect = searchBarRect;
		    treeRect.yMin = searchBarRect.yMax + VerticalSpacing;
		    treeRect.yMax = displayRect.yMax - EditPanelHeight;
		    treeRect.height = 100.0f >= treeRect.height ? 100.0f : treeRect.height;

		    TableTree.DrawSelf(treeRect, iEvent);

		    var editPanelRect = treeRect;
		    editPanelRect.yMin = treeRect.yMax + VerticalSpacing;
		    editPanelRect.yMax = iRect.yMax - VerticalSpacing;
		    editPanelRect = DrawEditPanel(editPanelRect, iEvent);
		    
		    return displayRect;
		}

		/// <summary>
		/// 绘制编辑面板
		/// </summary>
		/// <param name="iRect">制矩形范围</param>
		/// <param name="iEvent">Event</param>
		/// <returns>制矩形范围</returns>
		private Rect DrawEditPanel(Rect iRect, Event iEvent)
		{
			var displayRect = iRect;

			var bgRect = displayRect;
			bgRect = UtilsGUIEx.DrawGenericBg(bgRect, iEvent);

			var defineBgRect = bgRect;
			defineBgRect.xMin += HorizontalSpacing;
			defineBgRect.xMax -= (EditButtonsWidth + HorizontalSpacing * 2);
			defineBgRect.yMin += VerticalSpacing;
			defineBgRect.yMax = defineBgRect.yMin + SingleLineHeight + VerticalSpacing;
			defineBgRect = DrawDefineEditPanel(defineBgRect, iEvent);

			var tipsBgRect = defineBgRect;
			tipsBgRect.y = defineBgRect.yMax + VerticalSpacing;
			tipsBgRect = DrawTipsEditPanel(tipsBgRect, iEvent);

			var platformBgRect = tipsBgRect;
			platformBgRect.y = tipsBgRect.yMax + VerticalSpacing;
			platformBgRect.height = PlatformsEditLineHeight - VerticalSpacing;
			platformBgRect = DrawPlatformsEditPanel(platformBgRect, iEvent, EditDefineLabelWidth + HorizontalSpacing);

			var editButtonsBgRect = defineBgRect;
			editButtonsBgRect.xMin = defineBgRect.xMax + HorizontalSpacing;
			editButtonsBgRect.xMax = displayRect.xMax - HorizontalSpacing;
			editButtonsBgRect.yMax = platformBgRect.yMax;
			editButtonsBgRect = DrawOperateButtonsEditPanel(editButtonsBgRect, iEvent);
            
			return displayRect;
		}

		/// <summary>
		/// 绘制编辑面板 - 宏
		/// </summary>
		/// <param name="iRect">制矩形范围</param>
		/// <param name="iEvent">Event</param>
		/// <returns>制矩形范围</returns>
		private Rect DrawDefineEditPanel(Rect iRect, Event iEvent)
		{
			var displayRect = iRect;

			var defineBgRect = UtilsGUIEx.DrawGenericBg(displayRect, iEvent);

			var defineLabelRect = defineBgRect;
			defineLabelRect.xMin += HorizontalSpacing;
			defineLabelRect.width = EditDefineLabelWidth;
			defineLabelRect = UtilsGUIEx.DrawLabel(defineLabelRect, iEvent, _defineLabel);

			var defineRect = defineLabelRect;
			defineRect.xMin = defineLabelRect.xMax + HorizontalSpacing;
			defineRect.xMax = defineBgRect.xMax - 1;
			defineRect.yMin += 1;
			defineRect.yMax -= 1;
			defineRect = UtilsGUIEx.DrawTextField(defineRect, iEvent, _curDefine.Define,
				iInputTxt =>
				{
					_curDefine.Define = iInputTxt;
				});
			
			return displayRect;
		}

		/// <summary>
		/// 绘制编辑面板 - Tips
		/// </summary>
		/// <param name="iRect">制矩形范围</param>
		/// <param name="iEvent">Event</param>
		/// <returns>制矩形范围</returns>
		private Rect DrawTipsEditPanel(Rect iRect, Event iEvent)
		{
			var displayRect = iRect;

			var tipsBgRect = UtilsGUIEx.DrawGenericBg(displayRect, iEvent);

			var tipsLabelRect = tipsBgRect;
			tipsLabelRect.xMin += HorizontalSpacing;
			tipsLabelRect.width = EditDefineLabelWidth;
			tipsLabelRect = UtilsGUIEx.DrawLabel(tipsLabelRect, iEvent, _tipsLabel);

			var tipsRect = tipsLabelRect;
			tipsRect.xMin = tipsLabelRect.xMax + HorizontalSpacing;
			tipsRect.xMax = tipsBgRect.xMax - 1;
			tipsRect.yMin += 1;
			tipsRect.yMax -= 1;
			tipsRect = UtilsGUIEx.DrawTextField(tipsRect, iEvent, _curDefine.Tips,
				iInputTxt =>
				{
					_curDefine.Tips = iInputTxt;
				});
			
			return displayRect;
		}

		/// <summary>
		/// 绘制编辑面板 - Platforms
		/// </summary>
		/// <param name="iRect">制矩形范围</param>
		/// <param name="iEvent">Event</param>
		/// <param name="iIndentWidth">缩进</param>
		/// <returns>制矩形范围</returns>
		private Rect DrawPlatformsEditPanel(Rect iRect, Event iEvent, float iIndentWidth)
		{
			var displayRect = iRect;

			var tipsBgRect = UtilsGUIEx.DrawGenericBg(displayRect, iEvent);

			var platformsRect = tipsBgRect;
			platformsRect.xMin += iIndentWidth;
			var platformWidth = (platformsRect.width - HorizontalSpacing * 5) / 6.0f;

			var platformRect = platformsRect;
			platformRect.xMax = platformsRect.xMin + EditToggleAndroidWidth;
			// Android
			platformRect = DrawPlatformEditPanel(platformRect, iEvent, 
				GuiExHelper.AndroidContent, _curDefine.Android,
				iOnOff =>
				{
					_curDefine.Android = iOnOff;
				});
			
			// iOS
			platformRect.x = platformRect.xMax;
			platformRect.width = EditToggleIosWidth;
			platformRect = DrawPlatformEditPanel(platformRect, iEvent, 
				GuiExHelper.IosContent, _curDefine.iOS,
				iOnOff =>
				{
					_curDefine.iOS = iOnOff;
				});
			
			// Pc
			platformRect.x = platformRect.xMax;
			platformRect.width = EditTogglePcWidth;
			platformRect = DrawPlatformEditPanel(platformRect, iEvent, 
				GuiExHelper.PcOneContent, _curDefine.Pc,
				iOnOff =>
				{
					_curDefine.Pc = iOnOff;
				});
			
			// Ps4
			platformRect.x = platformRect.xMax;
			platformRect.width = EditTogglePs4Width;
			platformRect = DrawPlatformEditPanel(platformRect, iEvent, 
				GuiExHelper.Ps4Content, _curDefine.Ps4,
				iOnOff =>
				{
					_curDefine.Ps4 = iOnOff;
				});
			
			// Ps5
			platformRect.x = platformRect.xMax;
			platformRect.width = EditTogglePs5Width;
			platformRect = DrawPlatformEditPanel(platformRect, iEvent, 
				GuiExHelper.Ps5Content, _curDefine.Ps5,
				iOnOff =>
				{
					_curDefine.Ps5 = iOnOff;
				});
			
			// XboxOne
			platformRect.x = platformRect.xMax;
			platformRect.width = EditToggleXboxoneWidth;
			platformRect = DrawPlatformEditPanel(platformRect, iEvent, 
				GuiExHelper.XboxOneContent, _curDefine.XboxOne,
				iOnOff =>
				{
					_curDefine.XboxOne = iOnOff;
				});
			
			return displayRect;
		}

		/// <summary>
		/// 绘制编辑面板 - Platform
		/// </summary>
		/// <param name="iRect">制矩形范围</param>
		/// <param name="iEvent">Event</param>
		/// <param name="iCaption">标题</param>
		/// <param name="iOnOff">On/Off</param>
		/// <param name="iOnChanged">值变更回调</param>
		/// <returns>制矩形范围</returns>
		private Rect DrawPlatformEditPanel(Rect iRect, Event iEvent, GUIContent iCaption, bool iOnOff, Action<bool> iOnChanged)
		{
			var displayRect = iRect;

			var toggleRect = displayRect;
			toggleRect.xMax = toggleRect.xMin + ToggleWidth;
			
			// Toggle
			EditorGUI.BeginChangeCheck();
			var androidOnOff = EditorGUI.Toggle(toggleRect, iOnOff);
			if (EditorGUI.EndChangeCheck())
			{
				if (androidOnOff != iOnOff)
				{
					iOnChanged.Invoke(androidOnOff);
				}
			}
			
			// 标题
			var captionRect = displayRect;
			captionRect.xMin = toggleRect.xMax;
			EditorGUI.LabelField(captionRect, iCaption);
			
			return displayRect;
		}

		/// <summary>
		/// 绘制编辑面板 - 操作按钮
		/// </summary>
		/// <param name="iRect">制矩形范围</param>
		/// <param name="iEvent">Event</param>
		/// <returns>制矩形范围</returns>
		private Rect DrawOperateButtonsEditPanel(Rect iRect, Event iEvent)
		{
			var displayRect = iRect;
			var bgRect = UtilsGUIEx.DrawGenericBg(displayRect, iEvent);

			var widthTmp = (bgRect.width - HorizontalSpacing * 3) / 2;
            
			var addBtnRect = bgRect;
			addBtnRect.xMin += HorizontalSpacing;
			addBtnRect.width = widthTmp;
			addBtnRect.y = bgRect.yMin + VerticalSpacing;
			addBtnRect.height = SingleLineHeight;
			
			// 追加按钮
			EditorGUI.BeginDisabledGroup(DefineEditState.Idle != State);
			addBtnRect = UtilsGUIEx.DrawButton(addBtnRect, iEvent, GuiExHelper.AddBtnContent,
				() =>
				{
					OnAddBtnClicked(_curDefine);
					_curDefine = DefineInfo.Create(); 
				});
			EditorGUI.EndDisabledGroup();
			
			var delBtnRect = addBtnRect;
			delBtnRect.x = addBtnRect.xMax + HorizontalSpacing;
			// 保存按钮
			EditorGUI.BeginDisabledGroup(DefineEditState.Editing != State);
			addBtnRect = UtilsGUIEx.DrawButton(delBtnRect, iEvent, GuiExHelper.SaveBtnContent,
				() =>
				{
					OnSaveBtnClicked(_curDefine);
					_curDefine = DefineInfo.Create(); 
				});
			EditorGUI.EndDisabledGroup();
			
			var applyBtnRect = delBtnRect;
			applyBtnRect.y = displayRect.yMax - VerticalSpacing - SingleLineHeight;
			// 应用按钮
			applyBtnRect = UtilsGUIEx.DrawButton(applyBtnRect, iEvent, GuiExHelper.ApplyBtnContent, Apply);
			
			return displayRect;
		}

		/// <summary>
		/// 绘制TableTree的列
		/// </summary>
		/// <param name="iRect">绘制矩形范围</param>
		/// <param name="iDefine">宏定义</param>
		/// <param name="iRowIndex">行索引</param>
		/// <param name="iColumnIndex">列索引</param>
		protected override void DrawTableTreeColumn(Rect iRect, DefineInfo iDefine, int iRowIndex, int iColumnIndex)
		{
			var column = (DefinesColumns)iColumnIndex;
			switch (column)
			{
				case DefinesColumns.Id:
                {
                    GUI.Label(iRect, UtilsGUIEx.CreateGuiContent($"{iRowIndex + 1}"), GuiExHelper.MiddleCenterLabel);
                }
					break;

				case DefinesColumns.Name:
                {
                    var defineCaption = GetDefineCaption(iDefine.Id, iDefine.Define, iDefine.Tips);
                    GUI.Label(iRect, defineCaption, GuiExHelper.MiddleLeftLabel);
                }
					break;

                case DefinesColumns.Android:
                {
                    var toggleRect = iRect;
                    var centerPosX = toggleRect.center.x;
                    centerPosX -= EditorConst.ToggleWidth / 2.0f;
                    toggleRect.x = centerPosX;
                    toggleRect.width = EditorConst.ToggleWidth;
                    
                    EditorGUI.BeginChangeCheck();
                    var toggleValue = EditorGUI.Toggle(toggleRect, iDefine.Android);
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (toggleValue != iDefine.Android)
                        {
	                        iDefine.Android = toggleValue;
	                        Export();
                        }
                    }
                }
                    break;
                case DefinesColumns.iOS:
                {
                    var toggleRect = iRect;
                    var centerPosX = toggleRect.center.x;
                    centerPosX -= EditorConst.ToggleWidth / 2.0f;
                    toggleRect.x = centerPosX;
                    toggleRect.width = EditorConst.ToggleWidth;
                    
                    EditorGUI.BeginChangeCheck();
                    var toggleValue = EditorGUI.Toggle(toggleRect, iDefine.iOS);
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (toggleValue != iDefine.iOS)
                        {
	                        iDefine.iOS = toggleValue;
	                        Export();
                        }
                    }
                }
                    break;
                case DefinesColumns.Pc:
                {
                    var toggleRect = iRect;
                    var centerPosX = toggleRect.center.x;
                    centerPosX -= EditorConst.ToggleWidth / 2.0f;
                    toggleRect.x = centerPosX;
                    toggleRect.width = EditorConst.ToggleWidth;
                    
                    EditorGUI.BeginChangeCheck();
                    var toggleValue = EditorGUI.Toggle(toggleRect, iDefine.Pc);
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (toggleValue != iDefine.Pc)
                        {
	                        iDefine.Pc = toggleValue;
	                        Export();
                        }
                    }
                }
                    break;
                case DefinesColumns.Ps4:
                {
                    var toggleRect = iRect;
                    var centerPosX = toggleRect.center.x;
                    centerPosX -= EditorConst.ToggleWidth / 2.0f;
                    toggleRect.x = centerPosX;
                    toggleRect.width = EditorConst.ToggleWidth;
                    
                    EditorGUI.BeginChangeCheck();
                    var toggleValue = EditorGUI.Toggle(toggleRect, iDefine.Ps4);
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (toggleValue != iDefine.Ps4)
                        {
	                        iDefine.Ps4 = toggleValue;
	                        Export();
                        }
                    }
                }
                    break;
                case DefinesColumns.Ps5:
                {
                    var toggleRect = iRect;
                    var centerPosX = toggleRect.center.x;
                    centerPosX -= EditorConst.ToggleWidth / 2.0f;
                    toggleRect.x = centerPosX;
                    toggleRect.width = EditorConst.ToggleWidth;
                    
                    EditorGUI.BeginChangeCheck();
                    var toggleValue = EditorGUI.Toggle(toggleRect, iDefine.Ps5);
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (toggleValue != iDefine.Ps5)
                        {
	                        iDefine.Ps5 = toggleValue;
	                        Export();
                        }
                    }
                }
                    break;
                case DefinesColumns.XboxOne:
                {
                    var toggleRect = iRect;
                    var centerPosX = toggleRect.center.x;
                    centerPosX -= EditorConst.ToggleWidth / 2.0f;
                    toggleRect.x = centerPosX;
                    toggleRect.width = EditorConst.ToggleWidth;
                    
                    EditorGUI.BeginChangeCheck();
                    var toggleValue = EditorGUI.Toggle(toggleRect, iDefine.XboxOne);
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (toggleValue != iDefine.XboxOne)
                        {
	                        iDefine.XboxOne = toggleValue;
	                        Export();
                        }
                    }
                }
                    break;
                case DefinesColumns.Operation:
                {
	                // 删除按钮
	                var delBtnRect = iRect;
	                delBtnRect.x = iRect.center.x;
	                delBtnRect.xMin -= BtnWidthIconOnly + 1;
	                delBtnRect.xMax = delBtnRect.xMin + BtnWidthIconOnly;
	                delBtnRect = UtilsGUIEx.DrawButton(delBtnRect, Event.current, GuiExHelper.DelIconBtnContent,
		                () =>
		                {
			                OnDelBtnClicked(iDefine);
		                }, Color.clear, GuiExHelper.PreButton);
                    
	                // 编辑按钮
	                var editBtnRect = delBtnRect;
	                editBtnRect.x = delBtnRect.xMax + HorizontalSpacing;
	                editBtnRect = UtilsGUIEx.DrawButton(editBtnRect, Event.current, GuiExHelper.EditIconBtnContent,
		                () =>
		                {
			                _curDefine = iDefine.Clone();
			                State = DefineEditState.Editing;
		                }, Color.clear, GuiExHelper.PreButton);
                }
                    break;
			}
		}

#endregion
        
    }
}
